package com.wave.wavesystem.business.service.impl;

import com.mybatisflex.core.query.QueryChain;
import com.wave.wavesystem.business.pojo.dto.user.UserLoginRequest;
import com.wave.wavesystem.business.pojo.dto.user.UserRegisterRequest;
import com.wave.wavesystem.business.pojo.emums.user.UserLogSuccessEnum;
import com.wave.wavesystem.business.pojo.emums.user.UserLogType;
import com.wave.wavesystem.business.pojo.entity.UserEntity;
import com.wave.wavesystem.business.pojo.entity.UserLoginLogEntity;
import com.wave.wavesystem.business.pojo.vo.user.UserLoginVO;
import com.wave.wavesystem.business.service.AuthService;
import com.wave.wavesystem.business.service.UserLoginLogService;
import com.wave.wavesystem.business.service.UserService;
import com.wave.wavesystem.common.constant.RequestConstant;
import com.wave.wavesystem.common.constant.UserConstant;
import org.springframework.beans.BeanUtils;
import wave.common.exception.WaveBusinessException;
import wave.common.pojo.enums.RStatusEnum;
import com.wave.wavesystem.common.util.AuthUtil;
import com.wave.wavesystem.common.util.Func;
import com.wave.wavesystem.common.util.ThrowUtil;
import com.wave.wavesystem.common.util.WebUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Service
public class AuthServiceImpl implements AuthService {

    @Resource
    private UserService userService;

    @Resource
    private UserLoginLogService loginLogService;

    @Override
    public UserLoginVO login(UserLoginRequest loginReq) {
        UserLoginLogEntity userLoginLog = new UserLoginLogEntity();
        userLoginLog.setLogType(UserLogType.LOGIN.getValue());
        userLoginLog.setThisLogIp(WebUtil.getIp());
        boolean existsUser = AuthUtil.existsUser();
        // 1、是否已经登录检测
        if (existsUser) {
            userLoginLog.setRemark(UserConstant.loginFailReason + UserLogSuccessEnum.EXISTS_FAIL.getText());
            userLoginLog.setSuccess(false);
            loginLogService.save(userLoginLog);
            UserEntity user = AuthUtil.getUser();
            UserLoginVO loginVO = new UserLoginVO();
            BeanUtils.copyProperties(user, loginVO);
            return loginVO;
        }
        // 2、校验验证码是否输入正确
        String code = (String) WebUtil.getRequest().getSession().getAttribute(RequestConstant.V_CODE);
        if (Func.isEmpty(code)) {
            userLoginLog.setRemark(UserConstant.loginFailReason + UserLogSuccessEnum.ILLEGAL_REQUEST.getText());
            userLoginLog.setSuccess(false);
            loginLogService.save(userLoginLog);
            throw new WaveBusinessException(RStatusEnum.FAIL);
        }
        if (Func.isFalse(code.equals(loginReq.getCode()))) {
            userLoginLog.setRemark(UserConstant.loginFailReason + UserLogSuccessEnum.CODE_FAIL.getText());
            userLoginLog.setSuccess(false);
            loginLogService.save(userLoginLog);
            throw new WaveBusinessException(RStatusEnum.FAIL);
        }
        // 3、账号是否正确检测
        UserEntity loginUser = userService.getOne(QueryChain.of(UserEntity.class)
                .eq(UserEntity::getAccount, loginReq.getAccount()));
        if (Func.isEmpty(loginUser)) {
            userLoginLog.setRemark(UserConstant.loginFailReason + UserLogSuccessEnum.ACCOUNT_FAIL.getText());
            userLoginLog.setSuccess(false);
            loginLogService.save(userLoginLog);
        }
        ThrowUtil.throwIf(Func.isEmpty(loginUser), RStatusEnum.SIGN_IN_FAIL);
        // 4、密码是否正确检测
        boolean passwordCheck = Func.isFalse(loginUser.getPassword().equals(loginReq.getPassword()));
        if (passwordCheck) {
            userLoginLog.setRemark(UserConstant.loginFailReason + UserLogSuccessEnum.PASSWORD_FAIL.getText());
            userLoginLog.setSuccess(false);
            userLoginLog.setUserId(loginUser.getId());
            loginLogService.save(userLoginLog);
        }
        ThrowUtil.throwIf(passwordCheck, RStatusEnum.SIGN_IN_FAIL);
        // 登录操作
        HttpServletRequest request = WebUtil.getRequest();
        request.getSession().setAttribute(RequestConstant.USER_INFO, loginUser);
        // 登录日志
        userLoginLog.setLogType(UserLogType.LOGIN.getValue());
        userLoginLog.setThisLogIp(WebUtil.getIp());
        userLoginLog.setUserId(loginUser.getId());
        userLoginLog.setSuccess(true);
        loginLogService.save(userLoginLog);
        UserLoginVO loginVO = new UserLoginVO();
        BeanUtils.copyProperties(loginUser, loginVO);
        return loginVO;
    }

    @Override
    public Boolean register(UserRegisterRequest registerRequest) {
        UserEntity one = userService.getOne(QueryChain.of(UserEntity.class)
                .eq(UserEntity::getAccount, registerRequest.getAccount()));
        ThrowUtil.throwIf(Func.isNotEmpty(one), RStatusEnum.FAIL, "请重写输入一个账号");
        UserEntity registerUser = new UserEntity();
        registerUser.setAccount(registerRequest.getAccount());
        registerUser.setPassword(registerRequest.getPassword());
        registerUser.setNickname(registerRequest.getNickname());
        userService.save(registerUser);
        // 注册日志
        UserLoginLogEntity userRegisterLog = new UserLoginLogEntity();
        userRegisterLog.setLogType(UserLogType.REGISTER.getValue());
        userRegisterLog.setThisLogIp(WebUtil.getIp());
        userRegisterLog.setUserId(registerUser.getId());
        userRegisterLog.setSuccess(true);
        return loginLogService.save(userRegisterLog);
    }

    @Override
    public Boolean logout(HttpServletRequest request) {
        Object user = request.getSession().getAttribute(RequestConstant.USER_INFO);
        if (Func.isEmpty(user)) return true;
        UserEntity userEntity = (UserEntity) user;
        request.getSession().removeAttribute(RequestConstant.USER_INFO);
        // 登出日志
        UserLoginLogEntity userLogoutLog = new UserLoginLogEntity();
        userLogoutLog.setLogType(UserLogType.LOGOUT.getValue());
        userLogoutLog.setThisLogIp(WebUtil.getIp());
        userLogoutLog.setUserId(userEntity.getId());
        userLogoutLog.setSuccess(true);
        loginLogService.save(userLogoutLog);
        return true;
    }


}
